﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using WMM.Tapioca;
using System.Xml.Linq;
using System.ComponentModel;
using WMM.Tapioca.Instance;
using System.Data;
using System.Xml;
using WMM.Tapioca.Taxonomy;
using WMM.Tapioca.Utilities;

namespace TapiocaWpf.Rendering
{
    /// <summary>
    /// Interaction logic for ReportModel.xaml
    /// </summary>
    public partial class ReportModel : Window
    {
        XbrlDocument xbrlDoc;

        public XbrlDocument XbrlDoc
        {
            get { return xbrlDoc; }
            set { xbrlDoc = value; }
        }

        InstanceDocument instance;

        XmlUrlResolver resolver;

        XDocument xModelStructure;
        XDocument xFactTable;
        XElement useNetworkElement;
        XElement factTableElement;

        private string networkLabel;
        private string networkIdentifier;
        private string tableName;

        List<string> arrayAxis;
        List<string> arraySlicers;
        List<string> arrayRows;
        List<string> arrayColumns;
        List<string> arrayTemp;

        private int level = 0;
        XNamespace ns = "";

        Dictionary<string, string> instantPeriods;
        
        private TableRow headerRow1;
        private TableRow headerRow2;
        private TableRow headerRow3;

        BackgroundWorker backgroundWorkerRendering = new BackgroundWorker();

        public ReportModel()
        {
            InitializeComponent();

            arrayAxis = new List<string>();
            arraySlicers = new List<string>();
            arrayRows = new List<string>();
            arrayColumns = new List<string>();
            arrayTemp = new List<string>();

            backgroundWorkerRendering.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorkerRendering_DoWork);
            backgroundWorkerRendering.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorkerRendering_RunWorkerCompleted);
                        
        }        


        internal void InitializeRendering(XmlUrlResolver resolver)
        {
            this.resolver = resolver;

            FillEntities();

            backgroundWorkerRendering.RunWorkerAsync(); 
        }


        private void FillEntities()
        {
            List<string> identifies = new List<string>();
            instance = xbrlDoc as InstanceDocument;

            foreach (Context context in instance.Contexts)
            {
                if (!ContainsString(identifies, context.Identifier))
                {
                    identifies.Add(context.Identifier);
                }
            }

            lbEntities.ItemsSource = identifies;
        }


        private bool ContainsString(List<string> identifies, string name)
        {
            foreach (string identifier in identifies)
            {
                if (identifier == name)
                {
                    return true;
                }
            }

            return false;
        }


        private void backgroundWorkerRendering_DoWork(object sender, DoWorkEventArgs e)
        {
            this.Dispatcher.Invoke((Action)(() =>
            {
                Mouse.OverrideCursor = Cursors.Wait;
            }));
            
            LoadModelStructure();

            LoadFactTable();            
        }


        private void backgroundWorkerRendering_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            BuildHypercube();

            Mouse.OverrideCursor = null;
        }


        private void LoadModelStructure()
        {
            this.Dispatcher.Invoke((Action)(() =>
            {
                this.MessageTextBlock.Text = "Loading ModelStructure...";
            }));

            string modelStructureLocation = @"http://www.xbrlsite.com/DigitalFinancialReporting/ReferenceImplementation/2013-05-15/abc-20121231_ModelStructure.xml";

            XmlReaderSettings settings = new XmlReaderSettings();
            settings.XmlResolver = resolver;

            XmlReader xmlReader = XmlTextReader.Create(modelStructureLocation, settings);

            xModelStructure = XDocument.Load(xmlReader, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);

            foreach (XElement network in xModelStructure.Root.Elements())
            {
                this.Dispatcher.Invoke((Action)(() =>
                {
                    lbNetworks.Items.Add(network.Attribute("label").Value);
                }));
            }
        }
        
         
        private void LoadFactTable()
        {
            this.Dispatcher.Invoke((Action)(() =>
            {
                this.MessageTextBlock.Text = "Loading FactTable...";
            }));

            string modelStructureLocation = @"http://www.xbrlsite.com/DigitalFinancialReporting/ReferenceImplementation/2013-05-15/abc-20121231_FactTable.xml";

            XmlReaderSettings settings = new XmlReaderSettings();
            settings.XmlResolver = resolver;

            XmlReader xmlReader = XmlTextReader.Create(modelStructureLocation, settings);

            xFactTable = XDocument.Load(xmlReader, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
        }        
        

        internal void BuildHypercube()
        {
            SelectUseNetwork();

            SelectFactTable();

            GetFactTableSlicersRowsColumns();

            AdjustSlicersRowsColumns();

            LoadSlicersInformation();

            LoadColumnInformation();

            LoadRowInformation();

            LoadFactValues();
        }


        private void SelectUseNetwork()
        {
            if (String.IsNullOrEmpty(networkLabel))
            {
                useNetworkElement = xModelStructure.Root.Elements().FirstOrDefault();
            }
            else
            {
                useNetworkElement = xModelStructure.Root.Elements().Where(e => e.Attribute("label").Value == networkLabel).FirstOrDefault();
            }

            networkLabel = (string)useNetworkElement.Attribute("label") ?? string.Empty;
            networkIdentifier = (string)useNetworkElement.Attribute("identifier") ?? string.Empty;

            XElement xTable = useNetworkElement.Element(ns + "Table");
            tableName = xTable.Attribute("name").Value;
        }


        private void SelectFactTable()
        {
            factTableElement = xFactTable.Descendants(ns + "Network").Where(e => e.Attribute("identifier").Value == networkIdentifier).FirstOrDefault();

            //tableName = factTableElement.Element(ns + "Table").Value;
        }


        private void GetFactTableSlicersRowsColumns()
        {
            int totalAxis = 0;
            int totalFacts = 0;

            XElement selectedNetwork = factTableElement.DescendantsAndSelf().Where(d => d.Name.LocalName == "Network" && d.Attribute("identifier").Value == networkIdentifier).FirstOrDefault();            
            XElement axesList = selectedNetwork.Descendants(ns + "Axes").FirstOrDefault();
            totalAxis = axesList.Elements().Count();

            IEnumerable<XElement> factList = selectedNetwork.Descendants(ns + "Fact");
            totalFacts = factList.Count();

            ClearContent();

            string masterMeasureName = null;
            string masterMeasureValue = null;

            foreach (XElement axis in axesList.Elements())
            {
                masterMeasureName = axis.Element("Name").Value;
                masterMeasureValue = axis.Element("Member").Value;

                arrayAxis.Add(masterMeasureName);

                IEnumerable<XElement> selectedNames = selectedNetwork.Descendants(ns + "Name").Where(d => d.Value == masterMeasureName);
                int countForSlicerStatus = 0;

                foreach (XElement xName in selectedNames)
                {
                    string selectedMeasureValue = xName.ElementsAfterSelf().FirstOrDefault().Value;

                    if (masterMeasureValue == selectedMeasureValue)
                    {
                        countForSlicerStatus = countForSlicerStatus + 1;
                    }
                    else
                    {
                    }
                }

                if (countForSlicerStatus == totalFacts && masterMeasureName != "xbrl:Period" &&
                    masterMeasureName != "xbrl:Concept") 
                {
                    //SLICER: This is a SLICER because ever [Axis] member is the same...
                    arraySlicers.Add(masterMeasureName);
                    arrayAxis.Remove(masterMeasureName);

                }
                else
                {
                    //NOT A SLICER: This is either a column or a row
                    switch (masterMeasureName)
                    {

                        case "xbrl:Concept":
                            //Put the concept [Axis] in the rows
                            arrayRows.Add(masterMeasureName);
                            break;

                        case "xbrl:Period":
                            //Put the period [Axis] in the columns if it is not a slicer
                            arrayColumns.Add(masterMeasureName);                            
                            break;

                        default:
                            //If you dont know where to put it, make it a column
                            arrayRows.Add(masterMeasureName);                            
                            break;
                    }

                }
            }
                          
        }


        private void ClearContent()
        {
            arrayAxis.Clear();
            arraySlicers.Clear();
            arrayRows.Clear();
            arrayColumns.Clear();
            arrayTemp.Clear();

            this.Dispatcher.Invoke((Action)(() =>
            {
                slidersParagraphs.Inlines.Clear();              
                table1.RowGroups.Clear();
            }));
        }


        private void AdjustSlicersRowsColumns()
        {
            int countSlicers = 0;
            int countRows = 0;
            int countColumns = 0;
            int countAxis = 0;
            int k_Temp = 0;

            countSlicers = arraySlicers.Count;
            countRows = arrayRows.Count;
            countColumns = arrayColumns.Count;
            countAxis = arrayAxis.Count;

            //NO COLUMNS, MORE THAN ONE SLICER: move one slicer to a column
            if (countSlicers > 2 & countColumns == 0)
            {
                //MsgBox "Move one of the rows to a column"

                for (int i = arraySlicers.Count - 1; i >= 0; i += -1)
                {

                    if (arraySlicers[i] == "xbrl:Period")
                    {
                        //Put it in the temporary location
                        arrayTemp.Add("xbrl:Period");
                        k_Temp = k_Temp + 1;

                        //Remove from existing list
                        arraySlicers.RemoveAt(i);
                        break; // TODO: might not be correct. Was : Exit For
                    }

                    arrayColumns.Add("xbrl:Period");
                }
            }


            //NO ROWS, MORE THAN ONE SLICER: move one slicer to a row
            if (countSlicers > 2 & countRows == 0)
            {
                //MsgBox "Move one of the rows to a column"
                for (int i = arraySlicers.Count - 1; i >= 0; i += -1)
                {

                    if (arraySlicers[i] == "xbrl:Concept")
                    {
                        //Put it in the temporary location
                        arrayTemp.Add("xbrl:Concept");
                        k_Temp = k_Temp + 1;

                        //Remove from existing list
                        arraySlicers.RemoveAt(i);

                        break; // TODO: might not be correct. Was : Exit For

                    }

                    arrayRows.Add("xbrl:Concept");
                }
            }           
        }


        private void LoadSlicersInformation()
        {
            string axisName = null;
            string axisMember = null;

            slidersParagraphs.Inlines.Add(new Run("\r\n"));

            foreach (string slicer in arraySlicers)
            {
                axisName = slicer;
                XElement xAxis = factTableElement.Descendants().Where(d => d.Name.LocalName == "Axis" && d.Element("Name").Value == axisName).FirstOrDefault();
                axisMember = xAxis.Element("Member").Value;

                this.Dispatcher.Invoke((Action)(() =>
                {
                    Bold b = new Bold();
                    b.Inlines.Add(axisName);
                    slidersParagraphs.Inlines.Add(b);
                    slidersParagraphs.Inlines.Add(new Run(" : " + axisMember + "\r\n"));
                }));                
            }

            slidersParagraphs.Background = this.FindResource(SystemColors.ActiveCaptionBrushKey) as Brush;
            slidersParagraphs.BorderBrush = new SolidColorBrush(Colors.Black);
            slidersParagraphs.BorderThickness = new Thickness(1, 1, 1, 1);
        }


        private void LoadColumnInformation()
        {
            XElement selectedNetwork;
            XElement selectedTable;
            XElement lineItems;

            IEnumerable<XElement> selectedAxis;
            IEnumerable<XElement> members;           

            string useMeasure = arrayColumns.ElementAt(0);
            //int column = 0;

            selectedNetwork = xModelStructure.Root.Elements().Where(e => e.Name.LocalName == "Network" && e.Attribute("identifier").Value == networkIdentifier).FirstOrDefault();
            selectedTable = selectedNetwork.Elements().Where(e => e.Name.LocalName == "Table" && e.Attribute("name").Value == tableName).FirstOrDefault();
            lineItems = selectedTable.Elements().Last();

            switch (useMeasure)
            {
                case "xbrl:Concept":
                    //This actually should get the last child of the table, the [Line Items].
                    selectedNetwork = xModelStructure.Root.Elements().Where(e => e.Name.LocalName == "Network" && e.Attribute("identifier").Value == networkIdentifier).FirstOrDefault();
                    selectedTable = selectedNetwork.Elements().Where(e => e.Name.LocalName == "Table" && e.Attribute("name").Value == tableName).FirstOrDefault();
                    lineItems = selectedTable.Elements().Last();
                    break;

                case "xbrl:Period":
                    selectedNetwork = xFactTable.Root.Descendants().Where(e => e.Name.LocalName == "Network" && e.Attribute("identifier").Value == networkIdentifier).FirstOrDefault();
                    selectedAxis = selectedNetwork.Descendants().Where(d => d.Name.LocalName == "Axis").Elements().Where(e => e.Name.LocalName == "Name" && e.Value == "xbrl:Period");
                    members = selectedAxis.Elements(ns + "Member");

                    List<string> arrayPeriods = new List<string>();

                    foreach (XElement member in members)
                    {
                        if (!ContainsString(arrayPeriods, member.Value))
                        {
                            arrayPeriods.Add(member.Value);
                        }
                    }

                    break;

                case "xbrl:Entity":
                    selectedNetwork = xFactTable.Root.Descendants().Where(e => e.Name.LocalName == "Network" && e.Attribute("identifier").Value == networkIdentifier).FirstOrDefault();
                    selectedAxis = selectedNetwork.Descendants().Where(d => d.Name.LocalName == "Axis").Elements().Where(e => e.Name.LocalName == "Name" && e.Value == "xbrl:Entity");
                    members = selectedAxis.Elements(ns + "Member");

                    List<string> arrayEntities = new List<string>();

                    foreach (XElement member in members)
                    {
                        if (!ContainsString(arrayEntities, member.Value))
                        {
                            arrayEntities.Add(member.Value);
                        }
                    }

                    break;

                default:
                    //FIXME                    
                    selectedNetwork = xModelStructure.Root.Elements().Where(e => e.Name.LocalName == "Network" && e.Attribute("identifier").Value == networkIdentifier).FirstOrDefault();
                    break;
            }         

            headerRow1 = new TableRow();
            headerRow1.Style = table1.FindResource("HeaderStyle") as Style;            

            headerRow2 = new TableRow();
            headerRow2.Style = table1.FindResource("HeaderStyle") as Style;            

            headerRow3 = new TableRow();
            headerRow3.Style = table1.FindResource("HeaderStyle") as Style;            

            instantPeriods = GetPeriodsFromContexts();

            foreach (string rowName in arrayRows)
            {
                if (rowName == "xbrl:Concept")
                {
                    TableCell headerCell = new TableCell(new Paragraph(new Run("")));
                    headerCell.BorderBrush = new SolidColorBrush(Colors.Black);
                    headerCell.BorderThickness = new Thickness(1, 1, 0, 0);
                    headerCell.Background = this.FindResource(SystemColors.ActiveCaptionBrushKey) as Brush;
                    headerCell.LineHeight = 33;
                    headerRow1.Cells.Add(headerCell);

                    TextBlock periodTextBlock = new TextBlock();
                    periodTextBlock.Text = networkLabel;
                    periodTextBlock.VerticalAlignment = VerticalAlignment.Bottom;

                    Grid gridContainer = new Grid();
                    gridContainer.Height = 33;
                    gridContainer.Children.Add(periodTextBlock);

                    BlockUIContainer blockUIContainer = new BlockUIContainer();
                    blockUIContainer.Child = gridContainer;

                    TableCell tableCell = new TableCell();
                    tableCell.Blocks.Add(blockUIContainer);

                    tableCell.BorderBrush = new SolidColorBrush(Colors.Black);
                    tableCell.BorderThickness = new Thickness(1, 0, 0, 1);
                    tableCell.Background = this.FindResource(SystemColors.ActiveCaptionBrushKey) as Brush;
                    headerRow2.Cells.Add(tableCell);

                    TableColumn tableColumn = new TableColumn();
                    tableColumn.Width = new GridLength(3, GridUnitType.Star);
                    table1.Columns.Add(tableColumn);
                }
            }

            foreach (string columnName in arrayColumns)
            {
                if (columnName == "xbrl:Period")
                {
                    TextBlock periodTextBlock = new TextBlock();
                    periodTextBlock.Text = "Period";                    
                    periodTextBlock.VerticalAlignment = VerticalAlignment.Bottom;

                    Grid gridContainer = new Grid();
                    gridContainer.Height = 33;                    
                    gridContainer.Children.Add(periodTextBlock);

                    BlockUIContainer blockUIContainer = new BlockUIContainer();
                    blockUIContainer.Child = gridContainer;
                    
                    TableCell tableCell = new TableCell();
                    tableCell.Blocks.Add(blockUIContainer);
                    tableCell.BorderBrush = new SolidColorBrush(Colors.Black);
                    tableCell.BorderThickness = new Thickness(1,1,1,1);
                    tableCell.Background = this.FindResource(SystemColors.ActiveCaptionBrushKey) as Brush;
                    tableCell.TextAlignment = TextAlignment.Center;
                    tableCell.ColumnSpan = instantPeriods.Values.Count;     

                    headerRow1.Cells.Add(tableCell);
                    //headerRow1.Cells[1].TextAlignment = TextAlignment.Center;
                    //headerRow1.Cells[1].ColumnSpan = instantPeriods.Values.Count;                    

                    foreach (string period in instantPeriods.Values)
                    {
                        TextBlock periodTextBlock2 = new TextBlock();
                        periodTextBlock2.Text = period;
                        periodTextBlock2.VerticalAlignment = VerticalAlignment.Bottom;

                        Grid gridContainer2 = new Grid();
                        gridContainer2.Height = 33;
                        gridContainer2.Children.Add(periodTextBlock2);

                        BlockUIContainer blockUIContainer2 = new BlockUIContainer();
                        blockUIContainer2.Child = gridContainer2;

                        TableCell periodCell = new TableCell();
                        periodCell.Blocks.Add(blockUIContainer2);

                        periodCell.BorderBrush = new SolidColorBrush(Colors.Black);
                        periodCell.BorderThickness = new Thickness(1,0,1,1);
                        periodCell.TextAlignment = TextAlignment.Center;
                        headerRow2.Cells.Add(periodCell);

                        TableColumn tableColumn = new TableColumn();
                        tableColumn.Width = new GridLength(1, GridUnitType.Star);
                        table1.Columns.Add(tableColumn);
                    }
                }
                else
                {                    
                    TableCell headerCell = new TableCell(new Paragraph(new Run("")));
                    headerCell.BorderBrush = new SolidColorBrush(Colors.Black);
                    headerCell.BorderThickness = new Thickness(1, 1, 0, 0);
                    headerCell.Background = this.FindResource(SystemColors.ActiveCaptionBrushKey) as Brush;
                    headerCell.LineHeight = 33;
                    headerRow1.Cells.Add(headerCell);

                    TextBlock periodTextBlock = new TextBlock();
                    periodTextBlock.Text = columnName;
                    periodTextBlock.VerticalAlignment = VerticalAlignment.Bottom;

                    Grid gridContainer = new Grid();
                    gridContainer.Height = 33;
                    gridContainer.Children.Add(periodTextBlock);

                    BlockUIContainer blockUIContainer = new BlockUIContainer();
                    blockUIContainer.Child = gridContainer;

                    TableCell tableCell = new TableCell();
                    tableCell.Blocks.Add(blockUIContainer);
                    
                    tableCell.BorderBrush = new SolidColorBrush(Colors.Black);
                    tableCell.BorderThickness = new Thickness(1,0,0,1);
                    tableCell.Background = this.FindResource(SystemColors.ActiveCaptionBrushKey) as Brush;
                    headerRow2.Cells.Add(tableCell);

                    TableColumn tableColumn = new TableColumn();
                    tableColumn.Width = new GridLength(3, GridUnitType.Star);
                    table1.Columns.Add(tableColumn);
                }
            }

            foreach (string rowName in arrayRows)
            {
                ComboBox axisComboBox = new ComboBox();
                axisComboBox.Items.Add("[Axis]");
                axisComboBox.SelectedIndex = 0;

                if (rowName != "xbrl:Concept")
                {
                    axisComboBox.Items.Add(rowName);
                    axisComboBox.VerticalAlignment = VerticalAlignment.Bottom;
                    //axisComboBox.Width = 100;

                    Grid gridContainer = new Grid();
                    gridContainer.Height = 33;
                    gridContainer.Children.Add(axisComboBox);

                    BlockUIContainer blockUIContainer = new BlockUIContainer();
                    blockUIContainer.Child = gridContainer;

                    TableCell tableCell = new TableCell();
                    tableCell.Blocks.Add(blockUIContainer);

                    tableCell.BorderBrush = new SolidColorBrush(Colors.Black);
                    tableCell.BorderThickness = new Thickness(1, 1, 1, 1);
                    tableCell.Background = this.FindResource(SystemColors.ActiveCaptionBrushKey) as Brush;
                    headerRow2.Cells.Add(tableCell);

                    TableColumn tableColumn = new TableColumn();
                    tableColumn.Width = new GridLength(1, GridUnitType.Star);
                    //tableColumn.Width = new GridLength(60);
                    table1.Columns.Add(tableColumn);
                }
            }
        }


        private Dictionary<string, string> GetPeriodsFromContexts()
        {
            Dictionary<string, string> periods = new Dictionary<string, string>();

            foreach (Context context in instance.Contexts)
            {
                if (context.IsInstantPeriod && context.ExplicitMembers.Count == 0 && context.TypedMembers.Count == 0)
                {
                    periods.Add(context.Id, context.PeriodElement.Elements().FirstOrDefault().Value);
                }
            }

            return periods;
        }


        private void LoadRowInformation()
        {
            XElement selectedNetwork;
            XElement selectedTable;
            XElement lineItems;

            string useReportElement = arrayRows.ElementAt(0);

            switch (useReportElement)
            {
                case "xbrl:Concept":                    
                //This actually should get the last child of the table, the [Line Items].
                    selectedNetwork = xModelStructure.Root.Elements().Where(e => e.Name.LocalName == "Network" && e.Attribute("identifier").Value == networkIdentifier).FirstOrDefault();
                    selectedTable = selectedNetwork.Elements().Where(e => e.Name.LocalName == "Table" && e.Attribute("name").Value == tableName).FirstOrDefault();
                    lineItems = selectedTable.Elements().Last();
                    break;

                default:
                    //Not sure what this would actually grab
                    selectedNetwork = xModelStructure.Root.Elements().Where(e => e.Name.LocalName == "Network" && e.Attribute("identifier").Value == networkIdentifier).FirstOrDefault();
                    selectedTable = selectedNetwork.Elements().Where(e => e.Name.LocalName == "Table" && e.Attribute("name").Value == tableName).FirstOrDefault();
                    lineItems = selectedTable.Elements().Last();
                    break;               
            }

            switch (useReportElement)
            {
                case "xbrl:Concept":
                    level = 0;
                    
                    string label = selectedNetwork.Attribute("label").Value;

                    //Get concepts for extended link
                    level = level + 1;
                    LoadRowInformationChildNodes(selectedNetwork);
                    level = level - 1;
                    break;

                //Might need to adjust this.....xbrl:Period
                case "xbrl:Period":

                    break;
                case "xbrl:Entity":

                    break;
                default:
                    break;
            }


            IEnumerable<XElement> concepts = lineItems.Elements();

            table1.RowGroups.Add(new TableRowGroup());

            // Add the header row.
            table1.RowGroups[0].Rows.Add(headerRow1);
            table1.RowGroups[0].Rows.Add(headerRow2);

            TextBlock periodTextBlock = new TextBlock();
            periodTextBlock.Text = lineItems.Attribute("label").Value;
            periodTextBlock.VerticalAlignment = VerticalAlignment.Bottom;

            Grid gridContainer = new Grid();
            gridContainer.Height = 33;
            gridContainer.Children.Add(periodTextBlock);

            BlockUIContainer blockUIContainer = new BlockUIContainer();
            blockUIContainer.Child = gridContainer;

            TableCell labelCell3 = new TableCell();
            labelCell3.Blocks.Add(blockUIContainer);

            labelCell3.Background = new SolidColorBrush(Colors.AliceBlue);
            headerRow3.Cells.Add(labelCell3);
            table1.RowGroups[0].Rows.Add(headerRow3);

            foreach (XElement concept in concepts.Elements())
            {
                TableRow currentRow = new TableRow();
                currentRow.FontSize = 12;

                if (concept.Elements().Count() > 0)
                {
                    currentRow.FontWeight = System.Windows.FontWeights.Bold;
                }

                string label = "\t" + concept.Attribute("label").Value;
                TableCell labelCell = new TableCell(new Paragraph(new Run(label)));
                labelCell.BorderBrush = new SolidColorBrush(Colors.Black);
                labelCell.BorderThickness = new Thickness(0.5, 0.5, 0.5, 0.5);

                //labelCell.Background = new SolidColorBrush(Colors.AliceBlue);
                labelCell.Background = this.FindResource(SystemColors.GradientInactiveCaptionBrushKey) as Brush;

                labelCell.LineHeight = 18;
                currentRow.Cells.Add(labelCell);

                // Abstract
                string conceptName = concept.Attribute("name").Value.GetLocalName();

                if (conceptName.IndexOf("Abstract", 0) > 0)
                {
                    conceptName = conceptName.Remove(conceptName.IndexOf("Abstract", 0), 8);
                }

                for (int i = 0; i < instantPeriods.Count; i++)
                {
                    string value = GetValueFact(conceptName, instantPeriods.ElementAt(i).Key, instance.Facts);
                    double Num;

                    bool isNum = double.TryParse(value, out Num);

                    if (isNum)
                    {
                        double factValue = Convert.ToDouble(value);
                        TableCell valueCell = new TableCell(new Paragraph(new Run(String.Format("{0:#,##0}", factValue))));
                        valueCell.BorderBrush = new SolidColorBrush(Colors.Black);
                        valueCell.BorderThickness = new Thickness(0, 0.5, 0.5, 0.5);
                        valueCell.TextAlignment = TextAlignment.Right;

                        if (factValue < 0)
                        {
                            valueCell.Background = new SolidColorBrush(Colors.Red);
                            valueCell.Foreground = new SolidColorBrush(Colors.White);
                        }

                        currentRow.Cells.Add(valueCell);
                    }
                    else
                    {
                        TableCell valueCell = new TableCell(new Paragraph(new Run("")));
                        valueCell.BorderBrush = new SolidColorBrush(Colors.Black);
                        valueCell.BorderThickness = new Thickness(0, 0.5, 0.5, 0.5);
                        currentRow.Cells.Add(valueCell);
                    }
                }

                table1.RowGroups[0].Rows.Add(currentRow);

                LoadRowInformationChild("\t\t", concept);

            }

        }


        private void LoadRowInformationChild(string tab, XElement concept)
        {
            foreach (XElement concept2 in concept.Elements())
            {
                TableRow currentRow = new TableRow();
                currentRow.FontSize = 12;

                if (concept2.Elements().Count() > 0)
                {
                    currentRow.FontWeight = System.Windows.FontWeights.Bold;
                }

                TableCell labelCell = new TableCell(new Paragraph(new Run(tab + concept2.Attribute("label").Value)));
                labelCell.BorderBrush = new SolidColorBrush(Colors.Black);
                labelCell.BorderThickness = new Thickness(0, 0.5, 0.5, 0.5);
                //labelCell.Background = new SolidColorBrush(Colors.AliceBlue);
                labelCell.Background = this.FindResource(SystemColors.GradientInactiveCaptionBrushKey) as Brush;
                currentRow.Cells.Add(labelCell);
                
                string conceptName = concept2.Attribute("name").Value.GetLocalName();

                for (int i = 0; i < instantPeriods.Count; i++)
                {
                    double factValue = Convert.ToDouble(GetValueFact(conceptName, instantPeriods.ElementAt(i).Key, instance.Facts));
                    string value = String.Format("{0:#,##0}", factValue);
                    TableCell valueCell = new TableCell(new Paragraph(new Run(value)));
                    valueCell.BorderBrush = new SolidColorBrush(Colors.Black);
                    valueCell.BorderThickness = new Thickness(0, 0.5, 0.5, 0.5);
                    valueCell.TextAlignment = TextAlignment.Right;

                    if (factValue < 0)
                    {
                        valueCell.Background = new SolidColorBrush(Colors.Red);
                        valueCell.Foreground = new SolidColorBrush(Colors.White);
                    }

                    currentRow.Cells.Add(valueCell);                                   
                }

                table1.RowGroups[0].Rows.Add(currentRow);
                LoadRowInformationChild("\t\t\t", concept2);
            }
        }       


        private void LoadRowInformationChildNodes(XElement selectedNetwork)
        {
            foreach (XElement child in selectedNetwork.Elements())
            {
                string label = child.Attribute("label").Value;
                string name = child.Attribute("name").Value;
            }
        }      


        private void LoadFactValues()
        {
            //
            // Here we create a DataTable with four columns.
            //
            DataTable table = new DataTable();
            table.Columns.Add("Dosage", typeof(int));
            table.Columns.Add("Drug", typeof(string));
            table.Columns.Add("Patient", typeof(string));
            table.Columns.Add("Date", typeof(DateTime));

            //
            // Here we add five DataRows.
            //
            table.Rows.Add(25, "Indocin", "David", DateTime.Now);
            table.Rows.Add(50, "Enebrel", "Sam", DateTime.Now);
            table.Rows.Add(10, "Hydralazine", "Christoff", DateTime.Now);
            table.Rows.Add(21, "Combivent", "Janet", DateTime.Now);
            table.Rows.Add(100, "Dilantin", "Melanie", DateTime.Now);


            this.Dispatcher.Invoke((Action)(() =>
            {
                //dgRendering.ItemsSource = this.renderingTable.DefaultView;

                //dgRendering.Columns[0].Width = new DataGridLength(3, DataGridLengthUnitType.Star);
                ////dgRendering.UpdateLayout();
                ////datagridColumns.Columns[i].Width = datagridColumns.Columns[i].Header.ToString().Length + 100;

                //for (int i = 0; i < instantPeriods.Count; i++)
                //{
                //   // dgRendering.Columns[i + 1].HeaderStyle = 
                //    dgRendering.Columns[i + 1].Width = new DataGridLength(1, DataGridLengthUnitType.Star);
                //}

                //this.MessageTextBlock.Text = "Rendering finished.";
            }));


            
        }


        private void lbNetworks_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ClearContent();

            ListBoxItem lbi = ((sender as ListBox).SelectedItem as ListBoxItem);
            networkLabel = ((ListBox)sender).SelectedItem.ToString();

            BuildHypercube();
        }


        private string GetValueFact(string conceptName, string instantPeriod, List<Fact> factList)
        {
            if (conceptName == null)
            {
                return null;
            }

            foreach (Fact currentFact in factList)
            {
                var currentItem = currentFact as FactItem;

                if (currentItem != null)
                {
                    //currentItem.C
                    if (currentItem.Concept.Name.Equals(conceptName))
                    {
                        return currentItem.Value;
                    }
                }
            }

            return null;
        }
    }
}
